/**
 * Monaco Markdown 编辑器组件
 * Phase 1: 前端 MVP 使用
 * Phase 3: 添加图片和 PDF 上传功能
 * 
 * 功能：
 * - VS Code 级别的编辑体验
 * - Markdown 语法高亮
 * - 代码补全（code-block、table、link、image）
 * - 快捷键支持
 * - 自动保存提示
 * - 图片上传（工具栏按钮、拖拽、粘贴）
 * - PDF 文档上传（工具栏按钮、拖拽、粘贴）
 */

import React, { useRef, useEffect, useState, useCallback } from 'react';
import Editor, { loader } from '@monaco-editor/react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription
} from '@/components/ui/dialog';
import {
  Save,
  Eye,
  EyeOff,
  Maximize,
  Minimize,
  Copy,
  Check,
  Image as ImageIcon,
  FileText,
  Loader2
} from 'lucide-react';
import { cn } from '@/lib/utils';
import * as monaco from 'monaco-editor';
import ImageUploader from './image-uploader';
import { fileService } from '@/lib/api/services/file-service';

// 配置 Monaco Editor 使用本地资源，不从 CDN 加载
loader.config({ monaco });

const MonacoMarkdownEditor = ({
  value = '',
  onChange,
  onSave,
  height = '600px',
  theme = 'vs-dark',
  readOnly = false,
  showPreview = false,
  onTogglePreview,
  documentId = null, // Phase 3: 关联文档ID
  className = ''
}) => {
  const editorRef = useRef(null);
  const monacoRef = useRef(null);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [isSaved, setIsSaved] = useState(true);
  const [copied, setCopied] = useState(false);
  const [stats, setStats] = useState({ lines: 0, chars: 0, words: 0 });
  const [showUploadDialog, setShowUploadDialog] = useState(false);
  const [showPdfUploadDialog, setShowPdfUploadDialog] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState(0);

  // 保存处理函数（提前定义，供 handleEditorDidMount 使用）
  const handleSave = () => {
    if (onSave) {
      onSave(value);
      setIsSaved(true);
      setTimeout(() => setIsSaved(false), 2000);
    }
  };

  // 更新统计信息（提前定义，供 handleChange 使用）
  const updateStats = (content) => {
    const lines = content.split('\n').length;
    const chars = content.length;
    const words = content.split(/\s+/).filter(word => word.trim()).length;
    setStats({ lines, chars, words });
  };

  // 插入 Markdown 语法（提前定义，供 handleEditorDidMount 使用）
  const insertMarkdown = (before, after = '') => {
    const editor = editorRef.current;
    if (!editor || !monacoRef.current) return;

    const selection = editor.getSelection();
    if (!selection) {
      // 如果没有选择，在光标位置插入
      const position = editor.getPosition();
      if (!position) return;

      const range = new monacoRef.current.Range(
        position.lineNumber,
        position.column,
        position.lineNumber,
        position.column
      );
      try {
        editor.executeEdits('', [{
          range: range,
          text: `${before}${after}`
        }]);
      } catch (error) {
        console.error('插入 Markdown 失败:', error);
        return;
      }
    } else {
      try {
        const selectedText = editor.getModel().getValueInRange(selection);
        const newText = `${before}${selectedText}${after}`;

        editor.executeEdits('', [{
          range: selection,
          text: newText
        }]);
      } catch (error) {
        console.error('插入 Markdown 失败:', error);
        return;
      }
    }

    try {
      editor.focus();
    } catch (error) {
      console.error('编辑器焦点设置失败:', error);
    }
  };

  // 编辑器挂载完成
  const handleEditorDidMount = (editor, monaco) => {
    editorRef.current = editor;
    monacoRef.current = monaco;

    // 配置 Markdown 语言（避免重复注册）
    try {
      if (!monaco.languages.getLanguages().find(lang => lang.id === 'markdown')) {
        monaco.languages.register({ id: 'markdown' });
      }
    } catch (error) {
      // 如果已经注册，忽略错误
      console.warn('Markdown 语言注册警告:', error);
    }

    // Phase 3: 事件监听器在 useEffect 中注册，避免在挂载时 handleDrop/handlePaste 还未定义

    // 自定义快捷键：Ctrl+S 保存
    try {
      editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
        handleSave();
      });
    } catch (error) {
      console.error('注册保存快捷键失败:', error);
    }

    // 自定义快捷键：Ctrl+B 加粗
    try {
      editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB, () => {
        insertMarkdown('**', '**');
      });
    } catch (error) {
      console.error('注册加粗快捷键失败:', error);
    }

    // 自定义快捷键：Ctrl+I 斜体
    try {
      editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI, () => {
        insertMarkdown('*', '*');
      });
    } catch (error) {
      console.error('注册斜体快捷键失败:', error);
    }

    // 自定义代码补全
    try {
      monaco.languages.registerCompletionItemProvider('markdown', {
        provideCompletionItems: (model, position) => {
          const suggestions = [
            {
              label: 'code-block',
              kind: monaco.languages.CompletionItemKind.Snippet,
              insertText: '```${1:language}\n${2:code}\n```',
              insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
              documentation: '代码块'
            },
            {
              label: 'table',
              kind: monaco.languages.CompletionItemKind.Snippet,
              insertText: '| ${1:Header1} | ${2:Header2} |\n| --- | --- |\n| ${3:Cell1} | ${4:Cell2} |',
              insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
              documentation: '表格'
            },
            {
              label: 'link',
              kind: monaco.languages.CompletionItemKind.Snippet,
              insertText: '[${1:text}](${2:url})',
              insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
              documentation: '链接'
            },
            {
              label: 'image',
              kind: monaco.languages.CompletionItemKind.Snippet,
              insertText: '![${1:alt}](${2:url})',
              insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
              documentation: '图片'
            },
            {
              label: 'heading',
              kind: monaco.languages.CompletionItemKind.Snippet,
              insertText: '## ${1:标题}',
              insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
              documentation: '二级标题'
            },
            {
              label: 'list',
              kind: monaco.languages.CompletionItemKind.Snippet,
              insertText: '- ${1:item1}\n- ${2:item2}\n- ${3:item3}',
              insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
              documentation: '无序列表'
            }
          ];
          return { suggestions };
        }
      });
    } catch (error) {
      console.error('注册代码补全提供者失败:', error);
    }
  };

  // 内容变化
  const handleChange = (newValue) => {
    onChange?.(newValue || '');
    setIsSaved(false);
    updateStats(newValue || '');
  };

  // 复制内容
  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(value);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (error) {
      console.error('复制失败:', error);
    }
  };

  // Phase 3: 插入图片 Markdown 语法
  const insertImageMarkdown = (imageUrl, altText = '') => {
    const editor = editorRef.current;
    if (!editor || !monacoRef.current) {
      console.warn('编辑器未准备好，无法插入图片 Markdown');
      return;
    }

    try {
      const selection = editor.getSelection();
      let position;

      if (selection) {
        position = selection.getStartPosition();
      } else {
        // 如果没有选择，使用当前光标位置
        position = editor.getPosition();
        if (!position) {
          console.warn('无法获取光标位置');
          return;
        }
      }

      const imageSyntax = `![${altText}](${imageUrl})`;

      // 在光标位置插入图片语法
      try {
        editor.executeEdits('', [{
          range: new monacoRef.current.Range(
            position.lineNumber,
            position.column,
            position.lineNumber,
            position.column
          ),
          text: imageSyntax
        }]);
      } catch (error) {
        console.error('执行编辑操作失败:', error);
        return;
      }

      try {
        editor.focus();
      } catch (error) {
        console.error('编辑器焦点设置失败:', error);
      }
    } catch (error) {
      console.error('插入图片 Markdown 失败:', error);
    }
  };

  // Phase 3: 处理图片上传
  const handleImageUpload = useCallback(async (file) => {
    if (!file) return;

    setUploading(true);
    setUploadProgress(0);

    try {
      // 先插入占位符
      const placeholder = '![上传中...](uploading)';
      insertImageMarkdown(placeholder, '上传中...');

      // 上传文件（Monaco 编辑器上传，设置 uploadSource='editor'）
      const fileMetadata = await fileService.upload(
        file,
        {
          fileType: 'image',
          documentId: documentId,
          compress: true,
          generateThumbnail: true,
          uploadSource: 'editor'  // 标识为 Monaco 编辑器上传
        },
        (percent) => {
          setUploadProgress(percent);
        }
      );

      // 获取图片URL（优先使用缩略图，如果没有则使用原图）
      const imageUrl = fileMetadata.thumbnailUrl || fileMetadata.fileUrl;

      // 替换占位符为实际URL
      const editor = editorRef.current;
      if (editor) {
        const model = editor.getModel();
        const content = model.getValue();
        const newContent = content.replace(placeholder, `![${fileMetadata.fileName}](${imageUrl})`);
        model.setValue(newContent);
      }

      setUploading(false);
      setUploadProgress(0);
      setShowUploadDialog(false);
    } catch (error) {
      console.error('图片上传失败:', error);
      // 移除占位符
      const editor = editorRef.current;
      if (editor) {
        const model = editor.getModel();
        const content = model.getValue();
        const newContent = content.replace(/!\[上传中\.\.\.\]\(uploading\)/g, '');
        model.setValue(newContent);
      }
      setUploading(false);
      setUploadProgress(0);
      alert('图片上传失败: ' + (error.message || '未知错误'));
    }
  }, [documentId]);

  // Phase 3: 处理 PDF 文件上传
  const handlePdfUpload = useCallback(async (file) => {
    if (!file) return;

    // 验证文件类型
    if (!file.type.includes('pdf') && !file.name.toLowerCase().endsWith('.pdf')) {
      alert('只支持 PDF 文件');
      return;
    }

    setUploading(true);
    setUploadProgress(0);

    try {
      // 先插入占位符
      const placeholder = '![上传中...](uploading)';
      insertImageMarkdown(placeholder, '上传中...');

      // 上传文件（Monaco 编辑器上传，设置 uploadSource='editor'）
      const fileMetadata = await fileService.upload(
        file,
        {
          fileType: 'document',
          documentId: documentId,
          compress: false,  // PDF 不压缩
          generateThumbnail: false,  // PDF 不生成缩略图
          uploadSource: 'editor'  // 标识为 Monaco 编辑器上传
        },
        (percent) => {
          setUploadProgress(percent);
        }
      );

      // 获取 PDF URL
      const pdfUrl = fileMetadata.fileUrl;

      // 替换占位符为实际URL（使用图片语法，Markdown 渲染器会自动识别 PDF）
      const editor = editorRef.current;
      if (editor) {
        const model = editor.getModel();
        const content = model.getValue();
        // 提取文件名（不含扩展名）作为 alt 文本
        const fileName = fileMetadata.fileName.replace(/\.pdf$/i, '');
        const newContent = content.replace(placeholder, `![${fileName}](${pdfUrl})`);
        model.setValue(newContent);
      }

      setUploading(false);
      setUploadProgress(0);
      setShowPdfUploadDialog(false);
    } catch (error) {
      console.error('PDF 上传失败:', error);
      // 移除占位符
      const editor = editorRef.current;
      if (editor) {
        const model = editor.getModel();
        const content = model.getValue();
        const newContent = content.replace(/!\[上传中\.\.\.\]\(uploading\)/g, '');
        model.setValue(newContent);
      }
      setUploading(false);
      setUploadProgress(0);
      alert('PDF 上传失败: ' + (error.message || '未知错误'));
    }
  }, [documentId]);

  // Phase 3: 处理粘贴事件（图片和 PDF）
  const handlePaste = useCallback(async (e) => {
    const items = e.clipboardData?.items;
    if (!items) return;

    for (let i = 0; i < items.length; i++) {
      const item = items[i];
      // 支持图片和 PDF
      if (item.type.startsWith('image/')) {
        e.preventDefault();
        e.stopPropagation();
        const file = item.getAsFile();
        if (file) {
          await handleImageUpload(file);
          break;
        }
      } else if (item.type === 'application/pdf' || item.kind === 'file') {
        // PDF 文件或文件类型
        e.preventDefault();
        e.stopPropagation();
        const file = item.getAsFile();
        if (file && (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf'))) {
          await handlePdfUpload(file);
          break;
        }
      }
    }
  }, [handleImageUpload, handlePdfUpload]);

  // Phase 3: 处理拖拽事件（图片和 PDF）
  const handleDrop = useCallback(async (e) => {
    e.preventDefault();
    e.stopPropagation();

    const files = e.dataTransfer?.files;
    if (!files || files.length === 0) return;

    const file = files[0];
    if (file.type.startsWith('image/')) {
      await handleImageUpload(file);
    } else if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) {
      await handlePdfUpload(file);
    }
  }, [handleImageUpload, handlePdfUpload]);

  // Phase 3: 处理拖拽悬停
  const handleDragOver = useCallback((e) => {
    e.preventDefault();
    e.stopPropagation();
  }, []);

  // Phase 3: 清理事件监听器
  useEffect(() => {
    const editor = editorRef.current;
    if (!editor || readOnly) return;

    const editorContainer = editor.getContainerDomNode();
    editorContainer.addEventListener('drop', handleDrop);
    editorContainer.addEventListener('dragover', handleDragOver);
    editorContainer.addEventListener('paste', handlePaste);

    return () => {
      editorContainer.removeEventListener('drop', handleDrop);
      editorContainer.removeEventListener('dragover', handleDragOver);
      editorContainer.removeEventListener('paste', handlePaste);
    };
  }, [handleDrop, handleDragOver, handlePaste, readOnly]);

  // 初始化统计
  useEffect(() => {
    updateStats(value);
  }, [value]);

  // 当 value prop 变化时，更新编辑器内容（处理外部数据加载的情况）
  useEffect(() => {
    const editor = editorRef.current;
    if (editor && value !== undefined) {
      const currentValue = editor.getValue();
      // 只在内容确实不同时才更新，避免不必要的光标跳转
      if (currentValue !== value) {
        editor.setValue(value);
      }
    }
  }, [value]);

  // 全屏切换
  const toggleFullscreen = () => {
    setIsFullscreen(!isFullscreen);
  };

  return (
    <div
      className={cn(
        "flex flex-col border rounded-lg overflow-hidden bg-gray-900",
        isFullscreen && "fixed inset-0 z-50",
        className
      )}
    >
      {/* 工具栏 */}
      <div className="flex items-center justify-between gap-2 px-4 py-2 bg-gray-800 border-b border-gray-700">
        <div className="flex items-center gap-2">
          <Badge variant="outline" className="text-xs">
            Markdown
          </Badge>

          {!isSaved && (
            <Badge variant="secondary" className="text-xs">
              未保存
            </Badge>
          )}

          {isSaved && (
            <Badge variant="default" className="text-xs bg-green-600">
              <Check className="size-3 mr-1" />
              已保存
            </Badge>
          )}
        </div>

        <div className="flex items-center gap-1">
          {/* 统计信息 */}
          <span className="text-xs text-gray-400 mr-2">
            {stats.lines} 行 · {stats.chars} 字符 · {stats.words} 词
          </span>

          {/* 图片上传按钮 - Phase 3 */}
          {!readOnly && (
            <Button
              variant="ghost"
              size="sm"
              onClick={() => setShowUploadDialog(true)}
              title="上传图片"
              className="h-7 px-2 text-gray-300 hover:text-white hover:bg-gray-700"
              disabled={uploading}
            >
              {uploading ? (
                <Loader2 className="size-4 animate-spin" />
              ) : (
                <ImageIcon className="size-4" />
              )}
            </Button>
          )}

          {/* PDF 上传按钮 - Phase 3 */}
          {!readOnly && (
            <Button
              variant="ghost"
              size="sm"
              onClick={() => setShowPdfUploadDialog(true)}
              title="上传 PDF 文档"
              className="h-7 px-2 text-gray-300 hover:text-white hover:bg-gray-700"
              disabled={uploading}
            >
              {uploading ? (
                <Loader2 className="size-4 animate-spin" />
              ) : (
                <FileText className="size-4" />
              )}
            </Button>
          )}

          {/* 复制按钮 */}
          <Button
            variant="ghost"
            size="sm"
            onClick={handleCopy}
            title="复制内容"
            className="h-7 px-2 text-gray-300 hover:text-white hover:bg-gray-700"
          >
            {copied ? (
              <Check className="size-4 text-green-500" />
            ) : (
              <Copy className="size-4" />
            )}
          </Button>

          {/* 预览切换 */}
          {onTogglePreview && (
            <Button
              variant="ghost"
              size="sm"
              onClick={onTogglePreview}
              title={showPreview ? "隐藏预览" : "显示预览"}
              className="h-7 px-2 text-gray-300 hover:text-white hover:bg-gray-700"
            >
              {showPreview ? (
                <EyeOff className="size-4" />
              ) : (
                <Eye className="size-4" />
              )}
            </Button>
          )}

          {/* 全屏切换 */}
          <Button
            variant="ghost"
            size="sm"
            onClick={toggleFullscreen}
            title={isFullscreen ? "退出全屏" : "全屏"}
            className="h-7 px-2 text-gray-300 hover:text-white hover:bg-gray-700"
          >
            {isFullscreen ? (
              <Minimize className="size-4" />
            ) : (
              <Maximize className="size-4" />
            )}
          </Button>

          {/* 保存按钮 */}
          {onSave && (
            <Button
              variant="ghost"
              size="sm"
              onClick={handleSave}
              disabled={readOnly}
              className="h-7 px-2 text-gray-300 hover:text-white hover:bg-gray-700"
            >
              <Save className="size-4 mr-1" />
              保存
            </Button>
          )}
        </div>
      </div>

      {/* 编辑器 */}
      <div className="flex-1">
        <Editor
          height={isFullscreen ? '100%' : height}
          language="markdown"
          theme={theme}
          value={value}
          onChange={handleChange}
          onMount={handleEditorDidMount}
          options={{
            readOnly,
            minimap: { enabled: false },
            fontSize: 14,
            lineNumbers: 'on',
            renderWhitespace: 'selection',
            scrollBeyondLastLine: false,
            wordWrap: 'on',
            tabSize: 2,
            automaticLayout: true,
            folding: true,
            lineDecorationsWidth: 10,
            lineNumbersMinChars: 4,
            renderLineHighlight: 'all',
            scrollbar: {
              vertical: 'auto',
              horizontal: 'auto',
              useShadows: false,
              verticalScrollbarSize: 10,
              horizontalScrollbarSize: 10
            },
            matchBrackets: 'always',
            suggest: {
              showKeywords: true,
              showSnippets: true
            },
            quickSuggestions: {
              other: true,
              comments: false,
              strings: false
            }
          }}
        />
      </div>

      {/* 快捷键提示 */}
      {
        !readOnly && (
          <div className="px-4 py-1.5 bg-gray-800 border-t border-gray-700 text-xs text-gray-400">
            <span className="mr-4">💡 快捷键：</span>
            <span className="mr-3">Ctrl+S 保存</span>
            <span className="mr-3">Ctrl+B 加粗</span>
            <span className="mr-3">Ctrl+I 斜体</span>
            <span className="mr-3">Ctrl+V 粘贴图片/PDF</span>
            <span>输入代码片段名称后按 Tab 补全</span>
          </div>
        )
      }

      {/* 图片上传对话框 - Phase 3 */}
      <Dialog open={showUploadDialog} onOpenChange={setShowUploadDialog}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>上传图片</DialogTitle>
            <DialogDescription>
              选择图片文件或拖拽图片到此处，支持 JPG、PNG、GIF、WebP 格式
            </DialogDescription>
          </DialogHeader>
          <ImageUploader
            onSuccess={(fileMetadata) => {
              const imageUrl = fileMetadata.thumbnailUrl || fileMetadata.fileUrl;
              insertImageMarkdown(imageUrl, fileMetadata.fileName);
              setShowUploadDialog(false);
            }}
            onError={(error) => {
              console.error('上传失败:', error);
              alert('图片上传失败: ' + (error.message || '未知错误'));
            }}
            onProgress={setUploadProgress}
            documentId={documentId}
            fileType="image"
            compress={true}
            maxSizeMB={10}
            uploadSource="editor"  // Monaco 编辑器上传
          />
        </DialogContent>
      </Dialog>

      {/* PDF 上传对话框 - Phase 3 */}
      <Dialog open={showPdfUploadDialog} onOpenChange={setShowPdfUploadDialog}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>上传 PDF 文档</DialogTitle>
            <DialogDescription>
              选择 PDF 文件或拖拽 PDF 到此处，最大 50MB。上传后可在文档中直接查看 PDF 内容。
            </DialogDescription>
          </DialogHeader>
          <ImageUploader
            onSuccess={(fileMetadata) => {
              const pdfUrl = fileMetadata.fileUrl;
              // 提取文件名（不含扩展名）作为 alt 文本
              const fileName = fileMetadata.fileName.replace(/\.pdf$/i, '');
              insertImageMarkdown(pdfUrl, fileName);
              setShowPdfUploadDialog(false);
            }}
            onError={(error) => {
              console.error('PDF 上传失败:', error);
              alert('PDF 上传失败: ' + (error.message || '未知错误'));
            }}
            onProgress={setUploadProgress}
            documentId={documentId}
            fileType="document"
            compress={false}
            maxSizeMB={50}
            accept="application/pdf"
            uploadSource="editor"  // Monaco 编辑器上传
          />
        </DialogContent>
      </Dialog>
    </div >
  );
};

export default MonacoMarkdownEditor;

